<template>
  <AFormItemRest>
    <AInput v-bind="$attrs" :value="props.value" style="cursor: pointer" readonly @click.stop="() => setOpen(true)">
      <template v-if="props.value" #suffix>
        <CloseCircleOutlined @click="() => emit('update:value', '')" />
      </template>
    </AInput>
  </AFormItemRest>

  <AModalPro title="选择图标" width="680px" :open="open" :footer="false" @cancel="() => setOpen(false)">
    <div class="icon-select-container">
      <div class="icon-select-search">
        <AFormItemRest>
          <AInput v-model:value="searchValue" placeholder="请输入图标名称" @change="onSearch" />
        </AFormItemRest>
      </div>
      <div v-show="!dataSource.length" class="icon-select-list__empty">
        <AEmpty />
      </div>
      <div v-show="dataSource.length" class="icon-select-list mini-scroll-bar" ref="target" @click="onSelect">
        <div
          class="icon-select-item"
          v-for="item in dataSource"
          :key="item"
          :class="{ 'item-selected': item === props.value }"
        >
          <div class="item__icon">
            <component :is="item" />
          </div>
          <div class="item__name">{{ item }}</div>
        </div>
      </div>
      <div class="pagination-container">
        <APagination
          size="middle"
          :current="pagination.pageNum"
          :pageSize="pagination.pageSize"
          :total="pagination.total"
          hideOnSinglePage
          @change="onPageChange"
        />
      </div>
    </div>
  </AModalPro>
</template>

<script setup>
import { onMounted, reactive, ref, toValue } from 'vue';
import { AModalPro } from '@/components/iteration';
import { useState } from '@/hooks';
import * as icons from '@ant-design/icons-vue';
import { CloseCircleOutlined } from '@ant-design/icons-vue';
import { useThrottle } from '@/hooks/common';

defineOptions({ inheritAttrs: false });

const props = defineProps({
  value: { type: String, default: '' }
});

const emit = defineEmits(['update:value']);

const iconList = Object.keys(icons).filter((item) => item.endsWith('Outlined'));
const target = ref();
const searchValue = ref('');
const [open, setOpen] = useState(false);

const pagination = reactive({
  pageNum: 1,
  pageSize: 30,
  total: iconList.length
});

const [dataSource, setDataSource] = useState([]);

onMounted(() => {
  setDataSource(iconList.slice(0, pagination.pageSize));
});

/**
 * 分页变化
 *
 * @param {number} pageNum
 * @param {number} pageSize
 * @returns void
 */
const onPageChange = (pageNum, pageSize) => {
  if (pageSize === pagination.pageSize) {
    pagination.pageNum = pageNum;
  } else {
    pagination.pageNum = 1;
  }
  pagination.pageSize = pageSize;
  const start = (pageNum - 1) * pageSize;
  setDataSource(iconList.slice(start, start + pageSize));
};

const onSearch = useThrottle(() => {
  const value = toValue(searchValue).toLowerCase();
  const data = iconList.filter((item) => item.toLowerCase().includes(value));
  pagination.pageNum = 1;
  pagination.total = data.length;
  setDataSource(data.slice(0, pagination.pageSize));
}, 400);

const onSelect = (e) => {
  const dom = e.target.closest('.icon-select-item');
  const [...children] = toValue(target).children;
  const index = children.indexOf(dom);

  if (index !== -1) {
    emit('update:value', toValue(dataSource)[index]);
    setOpen(false);
  }
};
</script>

<style lang="scss" scoped>
.icon-select-container {
  width: 100%;
  height: 40vh;
  padding: 16px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 16px;

  .icon-select-list__empty {
    flex-grow: 1;
  }

  .icon-select-list {
    flex-grow: 1;
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    overflow: hidden auto;
    gap: 8px;
    padding: 8px;
    user-select: none;

    .icon-select-item {
      width: 200px;
      display: flex;
      gap: 8px;
      border-radius: 4px;
      padding: 4px 12px;
      cursor: pointer;

      &.item-selected {
        color: var(--primary-active-color);
      }

      &:hover {
        background-color: var(--hover-bg-color);
      }
    }
  }

  .pagination-container {
    text-align: center;
  }
}
</style>
